/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 */


import { testInstrumentParam, testPreviewerParam } from '@ohos/coverage/lib/src/types/testTemplate';
import { generateOhosTestResult, generateUnitTestResult } from '@ohos/hvigor-arkts-compose';

export type queueListOpt = {
  params: testInstrumentParam | testPreviewerParam;
  resolve: (value: unknown) => void;
  reject: (reason?: any) => void;
};

type ExecuteCoverageType = 'generateUnitTestResult' | 'generateOhosTestResult';

/**
 * 命令行生成覆盖率报告的队列中心，保证多个模块输出覆盖率的场景下可以串行输出覆盖率报告避免冲突
 */
export class DeviceCoverageQueueCenter {
  private queueList: queueListOpt[] = [];

  // 队列状态控制，该字段为true时新进来的测试框架任务进入queue中，优先执行队列中的任务
  private isExecuting = false;
  private executeCoverageType: ExecuteCoverageType = 'generateOhosTestResult';

  constructor() {
    this.queueList = [];
  }

  async executeProxy(params: testInstrumentParam | testPreviewerParam, type?: ExecuteCoverageType) {
    if (type) {
      this.executeCoverageType = type;
    } else {
      this.executeCoverageType = 'generateOhosTestResult';
    }
    if (this.isExecuting) {
      return new Promise((resolve, reject) => {
        this.queueList.push({ params, resolve, reject });
      });
    }
    await this.innerExecuteProxy(params);
  }

  private async dequeue() {
    if (!this.queueList.length) {
      return;
    }
    const queue = this.queueList.shift();
    if (!queue) {
      return;
    }
    const { resolve, reject, params } = queue;
    try {
      await this.innerExecuteProxy(params);
      resolve(true);
    } catch (e) {
      reject(e);
    }
  }

  protected async innerExecuteProxy(params: testInstrumentParam | testPreviewerParam) {
    try {
      this.isExecuting = true;
      if (this.executeCoverageType === 'generateUnitTestResult') {
        await generateUnitTestResult(params as testPreviewerParam);
      } else {
        await generateOhosTestResult(params as testInstrumentParam);
      }

      // 测试框架异步任务执行结束后将isExecuting状态置为false，等待下一个任务执行
      this.isExecuting = false;
      this.dequeue();
    } catch (e) {
      this.isExecuting = false;
      this.queueList = [];
      throw e;
    }
  }
}

export const deviceCoverageQueueCenter = new DeviceCoverageQueueCenter();
